gusucode.com > VC 跳跃文字显示特效 > VC 跳跃文字显示特效/gusucode/JumpyText/JumpyDraw.cpp

    //Download by http://www.NewXing.com
// JumpyDraw.cpp : implementation file
//
// JumpyDraw is a animated static control control. Check out the 
// header file or the accompanying HTML doc file for details.
//
// Written by Fabian Toader (Fabi Pantera) (fabian_toader@hotmail.com)
// Copyright (c) 1999.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is 
// not sold for profit without the authors written consent, and 
// providing that this notice and the authors name is included. If 
// the source code in  this file is used in any commercial application 
// then a simple email would be nice.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage to your
// computer, causes your pet cat to fall ill, increases baldness or
// makes you car start emitting strange noises when you start it up.
//
// Expect bugs.
// 
// Please use and enjoy. Please let me know of any bugs/mods/improvements 
// that you have found/implemented and I will fix/incorporate them into this
// file. 
//

#include "stdafx.h"
#include "JumpyDraw.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define ID_JUMPY_REFRESH_DRAW WM_USER+1286 //the timer ID
const int LINEAR_WASH_SEGMENTS = 60; //used in the gradient function
/////////////////////////////////////////////////////////////////////////////
// CJumpyDraw

CJumpyDraw::CJumpyDraw()
{
	//default text goes here
	mstrJumpy = mstrActualText = "The quick brown fox jumps over the lazy dog. 1234567890";
	//default time period goes here
	mnTime = 1000;
	//default font name goes here
	mstrFont = "MS Sans Serif";
	//default char height goes here
	mnCharHeight = 24;
	//default text color goes here
	mTextColor = RGB(0, 255, 0);
	//default gradient colors goes here
	mGradientColorStart = RGB(123, 158, 198);
	mGradientColorEnd = RGB(0, 0, 255);
	//default shaddow color goes here
	mShaddowColor = RGB(0,0,0);
	mnIndexAleator = -1;
	mFontDummy.CreateFont(mnCharHeight, 0, 0, 0, 0,//nIsBold, 
		FALSE, //bIsItalic, 
		FALSE, //bIsUnderline, 
		0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, 
						 DEFAULT_QUALITY, DEFAULT_PITCH, mstrFont);
}

CJumpyDraw::~CJumpyDraw()
{
	mFontDummy.DeleteObject();
}


BEGIN_MESSAGE_MAP(CJumpyDraw, CStatic)
	//{{AFX_MSG_MAP(CJumpyDraw)
	ON_WM_TIMER()
	ON_WM_PAINT()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CJumpyDraw message handlers


//jumpy text function. Render the text using its parameters 
void CJumpyDraw::StartJumpyText(CString strJump, DWORD nTime, CString strFont, int nHeight, 
		COLORREF TextColor,	COLORREF ShaddowColor,
		COLORREF GradientColorStart,  
		COLORREF GradientColorEnd)

{
	CFont fontDummy;
	fontDummy.CreateFont(nHeight, 0, 0, 0, 0,//nIsBold, 
		FALSE, //bIsItalic, 
		FALSE, //bIsUnderline, 
		0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, 
						 DEFAULT_QUALITY, DEFAULT_PITCH, strFont);
	//set the new params
	mTextColor = TextColor;
	mGradientColorStart = GradientColorStart;
	mGradientColorEnd = GradientColorEnd;
	mShaddowColor = ShaddowColor;
	mFontDummy.DeleteObject();
	mFontDummy.Attach(fontDummy.Detach());
	SetFont(&mFontDummy);
	mstrJumpy = strJump;
	mnIndexAleator = -1;
	int nLenght = strJump.GetLength();
	mstrActualText = mstrJumpy;
	//start rendering
	KillTimer(ID_JUMPY_REFRESH_DRAW);
	SetTimer(ID_JUMPY_REFRESH_DRAW, (int)(nTime/nLenght), NULL);
}

//start jumpy function without parms. It use some default params which has been previously set
void CJumpyDraw::StartJumpyText()
{
	//set the font
	CFont fontDummy;
	fontDummy.CreateFont(mnCharHeight, 0, 0, 0, 0,//nIsBold, 
		FALSE, //bIsItalic, 
		FALSE, //bIsUnderline, 
		0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, 
						 DEFAULT_QUALITY, DEFAULT_PITCH, mstrFont);
	mFontDummy.DeleteObject();
	mFontDummy.Attach(fontDummy.Detach());
	SetFont(&mFontDummy);
	int nLenght = mstrJumpy	.GetLength();
	mstrActualText = mstrJumpy;
	mnIndexAleator = -1;
	//start rendering
	KillTimer(ID_JUMPY_REFRESH_DRAW);
	SetTimer(ID_JUMPY_REFRESH_DRAW, (int)(mnTime/nLenght), NULL);
}

//the timer handle
void CJumpyDraw::OnTimer(UINT nIDEvent) 
{
	if (ID_JUMPY_REFRESH_DRAW == nIDEvent)
	{
		mnIndexAleator++;//this member hold the index in the text
		if ((mnIndexAleator+1) == mstrJumpy.GetLength())
		{//the render should stop rendering
			KillTimer(ID_JUMPY_REFRESH_DRAW);
			CStatic::OnTimer(nIDEvent);
			mstrActualText = mstrJumpy;
			mnIndexAleator = -1;
			Invalidate();
			return;
		}
		CString strGet, strSet;
		GetWindowText(strGet);
		CString strShuffle = strGet;
		if (mnIndexAleator > 0)
			strShuffle = mstrJumpy.Right(mstrJumpy.GetLength() - mnIndexAleator);
		else
			strShuffle = mstrActualText;
		if (mnIndexAleator > 0)
			strSet = mstrJumpy.Left(mnIndexAleator);
		else
			strSet = "";
		//render just the right part
		ShuffleChars(strSet, strShuffle);
		//combine left and right part and force to redraw it
		strSet += strShuffle;
		mstrActualText = strSet;
		Invalidate();
	}
	CStatic::OnTimer(nIDEvent);
}

//function for shuffleing the strShuffle string
void CJumpyDraw::ShuffleChars(CString strLeft, CString &strShuffle)
{
	srand( (unsigned)time( NULL ) );
	for (int j=0; j<10;j++)
	{
		for (int i=0; i<3;i++)
		{
			int nFirst = rand() % strShuffle.GetLength();
			int nSecond = rand() % strShuffle.GetLength();
			TCHAR FirstChar = strShuffle.GetAt(nFirst);
			TCHAR SecondChar = strShuffle.GetAt(nSecond);
			strShuffle.SetAt(nFirst, SecondChar);
			strShuffle.SetAt(nSecond, FirstChar);
		}
		//combine the left and right part
		mstrActualText = strLeft+strShuffle;
		Invalidate();
	}
}

//the paint function. It simply draw the text and the gradient background
void CJumpyDraw::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	CRect rc;
	GetClientRect(&rc);
	//virtual dc used for non-flickering
	CDC dcMem;
	dcMem.CreateCompatibleDC(&dc);
	CBitmap bitmapMem;
	bitmapMem.CreateCompatibleBitmap(&dc, rc.Width(), rc.Height());
	CBitmap* pOldBit = dcMem.SelectObject(&bitmapMem);
	HBRUSH hbrBkGnd;
	hbrBkGnd = CreateSolidBrush(GetSysColor(COLOR_ACTIVECAPTION));
	CRect rectTemp(rc);
	rectTemp.left = 0;
	rectTemp.top = 0;
	FillRect(dcMem.m_hDC, &rectTemp, hbrBkGnd);    
	DeleteObject(hbrBkGnd);
	dcMem.SetBkMode(TRANSPARENT);

	//draw the gradient
	DrawLinearWash(&dcMem, &rc, 
		LINEAR_WASH_SEGMENTS, mGradientColorStart, mGradientColorEnd);

	CFont* pfontOld;
	pfontOld = dcMem.SelectObject(&mFontDummy);
	//draw shaddow text
	dcMem.SetTextColor(mShaddowColor);
	dcMem.DrawText(mstrActualText, rc, DT_VCENTER | DT_NOCLIP | DT_SINGLELINE | DT_CENTER);
	rc.top -= 4;
	rc.left -= 4;
	//draw text
	dcMem.SetTextColor(mTextColor);
	dcMem.DrawText(mstrActualText, rc, DT_VCENTER | DT_NOCLIP | DT_SINGLELINE | DT_CENTER);
	dcMem.SelectObject(pfontOld);
	dc.BitBlt(rc.left,rc.top,rc.Width(),rc.Height(),&dcMem,0,0,SRCCOPY);
	 // Done with off-screen bitmap and DC.    //
    dcMem.SelectObject(pOldBit);
	DeleteObject(bitmapMem.m_hObject);
	dcMem.DeleteDC();
}

//the gradient function
void CJumpyDraw::DrawLinearWash(CDC* pDC, CRect* prc, int iSegments,
						   COLORREF crStart, COLORREF crEnd)
{
	// Get the starting RGB values and calculate the incremental
	// changes to be applied.

	COLORREF cr;
	int iR = GetRValue(crStart);
	int iG = GetGValue(crStart);
	int iB = GetGValue(crStart);
	int idR = (GetRValue(crEnd) - iR) / (iSegments - 1);
	int idG = (GetGValue(crEnd) - iG) / (iSegments - 1);
	int idB = (GetBValue(crEnd) - iB) / (iSegments - 1);
	int icx = prc->Width() / iSegments, iLeft = prc->left, iRight;
	pDC->SelectStockObject(NULL_PEN);

	for (int i = 0; i < iSegments; i++, iR += idR, iG += idG, iB += idB)
	{
		// Use special code for the last segment to avoid any problems
		// with integer division.

		if (i == (iSegments - 1))
			iRight = prc->right;
		else
			iRight = iLeft + icx;

		cr = RGB(iR, iG, iB);
		
		// The following extra stack frame allocates and disposes
		// of the GDI objects nicely.

		{
			// Perform the drawing and restore the DC; the objects
			// will be freed automatically.

			CBrush br(cr);
			CBrush* pbrOld = pDC->SelectObject(&br);
			pDC->Rectangle(iLeft, prc->top, iRight + 1, prc->bottom);
			pDC->SelectObject(pbrOld);
		}

		// Reset the left side of the drawing rectangle.

		iLeft = iRight;
	}
}

//get/set functions
void CJumpyDraw::SetText(CString strValue)
{
	mstrJumpy = mstrActualText = strValue;
}

CString CJumpyDraw::GetText()
{
	return mstrJumpy;
}

void CJumpyDraw::SetFontFace(CString strFont)
{
	mstrFont = strFont;
}

CString CJumpyDraw::GetFontFace()
{
	return mstrFont;
}

int CJumpyDraw::GetCharHeight()
{
	return mnCharHeight;
}

void CJumpyDraw::SetCharHeight(int nHeight)
{
	mnCharHeight = nHeight;
}

COLORREF CJumpyDraw::GetTextColor()
{
	return mTextColor;
}

void CJumpyDraw::SetTextColor(COLORREF colourText)
{
	mTextColor = colourText;
}

COLORREF CJumpyDraw::GetGradientStartColor()
{
	return mGradientColorStart;
}

void CJumpyDraw::SetGradientStartColor(COLORREF startColor)
{
	mGradientColorStart = startColor;
}

COLORREF CJumpyDraw::GetGradientEndColor()
{
	return mGradientColorEnd;
}

void CJumpyDraw::SetGradientEndColor(COLORREF colourEnd)
{
	mGradientColorEnd = colourEnd;
}

COLORREF CJumpyDraw::GetShaddowColor()
{
	return mShaddowColor;
}

void CJumpyDraw::SetShaddowColor(COLORREF colorShaddow)
{
	mShaddowColor = colorShaddow;
}

void CJumpyDraw::SetJumpyTime(DWORD nTime)
{
	mnTime = nTime;
}

DWORD CJumpyDraw::GetJumpyTime()
{
	return mnTime;
}